﻿using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Windows;
using System.Collections.Generic;
using System.Windows.Media.Animation;
using System;
using System.Windows.Input;

namespace TouchUmlUI
{
    public class AssociationType : Canvas
    {
        public AssociationType(double px,double py)
        {
            this.Background = Brushes.Red;
            this.Width = 16;
            this.Height = 16;
        }
    }
    
    public class AssociationObj : UMLObj
    {

        public enum LineType { CURVE, CORNERED };
        public enum ConnectionPoint { WEST, NORTH, EAST, SOUTH };

        public int FROMES = 0;
        public int FROMNS = 0;
        public int TOES = 0;
        public int TONS = 0;

        private bool canChooseType;

        public bool corrected;
        private LineType lineType;
        public AssociableObj fromRef;
        public AssociableObj toRef;        
        Polygon fromPolygon = new Polygon();
        Polygon toPolygon = new Polygon();
        Line line = new Line();
        public Line[] polyline = new Line[3];
        Canvas fromMenu = new Canvas();
        Canvas toMenu = new Canvas();
        AssociationHint associationHintFrom;
        AssociationHint associationHintTo;
        ConnectionPoint fromConnectionPoint;
        ConnectionPoint toConnectionPoint;
        double lx1,lx2,lx3,lx4,ly1,ly2,ly3,ly4;
        private int id;
        Point pFrom;
        Point pTo;


        Rectangle fromR, toR;
        TextBlock fromT, toT;

        public override void showHints(bool a_show)
        {
            int thick = a_show ? 1 : 0;           
            fromR.StrokeThickness = thick;
            toR.StrokeThickness = thick;            
        }


        public void from_MouseDown(object sender, MouseButtonEventArgs e)
        {            
            if (SignalR.windowParent.handWrite != null) return;
            SignalR.windowParent.handWrite = new UCUTextRecognizer.HandWrite();
            UCUTextRecognizer.HandWrite handWrite = SignalR.windowParent.handWrite;
            handWrite.InitializeComponent();
            try
            {
                if (!(((Diagram.Asocjacja)guml.obj_uml)[0].Tekst).StartsWith("..."))
                {
                    handWrite.setExistingText(((Diagram.Asocjacja)guml.obj_uml)[0].Tekst);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            
            double sy = Canvas.GetTop(fromR) - 50;
            double sx = SignalR.windowParent.sv.HorizontalOffset + 50;
            double nw = SignalR.windowParent.sv.ActualWidth - 100;
            double nh = 180;
            

            handWrite.Width = nw;
            handWrite.Height = nh;
            InkCanvas.SetLeft(handWrite, sx);
            InkCanvas.SetTop(handWrite, sy);
            handWrite.Opacity = 1.0f;
            //
            handWrite.bindWithKoncowka(((Diagram.Asocjacja)guml.obj_uml)[0],true,this);
            SignalR.windowParent.active_canvas.Children.Add(handWrite);
            e.Handled = true;
        }

        public void to_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (SignalR.windowParent.handWrite != null) return;
            SignalR.windowParent.handWrite = new UCUTextRecognizer.HandWrite();
            UCUTextRecognizer.HandWrite handWrite = SignalR.windowParent.handWrite;
            handWrite.InitializeComponent();
            try
            {
                if (!(((Diagram.Asocjacja)guml.obj_uml)[1].Tekst).StartsWith("..."))
                {
                    handWrite.setExistingText(((Diagram.Asocjacja)guml.obj_uml)[1].Tekst);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            
            double sy = Canvas.GetTop(toR) - 50;
            double sx = SignalR.windowParent.sv.HorizontalOffset + 50;
            double nw = SignalR.windowParent.sv.ActualWidth - 100;
            double nh = 180;            

            handWrite.Width = nw;
            handWrite.Height = nh;
            InkCanvas.SetLeft(handWrite, sx);
            InkCanvas.SetTop(handWrite, sy);
            handWrite.Opacity = 1.0f;
            //
            handWrite.bindWithKoncowka(((Diagram.Asocjacja)guml.obj_uml)[0], false, this);
            SignalR.windowParent.active_canvas.Children.Add(handWrite);
            e.Handled = true;
        }

        public void setTextBlockPositions()
        {
            fromT.Text = ((Diagram.Asocjacja)guml.obj_uml)[0].Tekst;
            toT.Text = ((Diagram.Asocjacja)guml.obj_uml)[1].Tekst;            
            guml.panel.UpdateLayout();
            if (fromConnectionPoint == ConnectionPoint.EAST)
            {
                double fromX = polyline[0].X1 + 3;
                double fromY = polyline[0].Y1 - 30;
                double fromWidth = fromT.ActualWidth + 10;
                double fromHeight = fromT.ActualHeight + 10;
                // ---
                fromR.Width = fromWidth;
                fromR.Height = fromHeight;
                Canvas.SetLeft(fromR, fromX);
                Canvas.SetTop(fromR, fromY);
                Canvas.SetLeft(fromT, fromX + 5);
                Canvas.SetTop(fromT, fromY + 5);

                double toX = polyline[2].X2 - toT.ActualWidth - 12;
                double toY = polyline[2].Y2 - 30;
                double toWidth = toT.ActualWidth + 10;
                double toHeight = toT.ActualHeight + 10;
                // ---
                toR.Width = toWidth;
                toR.Height = toHeight;
                Canvas.SetLeft(toR, toX);
                Canvas.SetTop(toR, toY);
                Canvas.SetLeft(toT, toX + 5);
                Canvas.SetTop(toT, toY + 5);
            }
            else if (fromConnectionPoint == ConnectionPoint.WEST)
            {
                double fromX = polyline[2].X2 + 3;
                double fromY = polyline[2].Y2 - 30;
                double fromWidth = fromT.ActualWidth + 10;
                double fromHeight = fromT.ActualHeight + 10;
                // ---


                double toX = polyline[0].X1 - fromT.ActualWidth - 12;
                double toY = polyline[0].Y1 - 30;
                double toWidth = toT.ActualWidth + 10;
                double toHeight = toT.ActualHeight + 10;
                // ---

                fromR.Width = fromWidth;
                fromR.Height = fromHeight;
                Canvas.SetLeft(toR, fromX);
                Canvas.SetTop(toR, fromY);
                Canvas.SetLeft(toT, fromX + 5);
                Canvas.SetTop(toT, fromY + 5);

                toR.Width = toWidth;
                toR.Height = toHeight;
                Canvas.SetLeft(fromR, toX);
                Canvas.SetTop(fromR, toY);
                Canvas.SetLeft(fromT, toX + 5);
                Canvas.SetTop(fromT, toY + 5);
            }
            else if (fromConnectionPoint == ConnectionPoint.SOUTH)
            {
                double fromX = polyline[0].X1 + 3;
                double fromY = polyline[0].Y1 + 3;
                double fromWidth = fromT.ActualWidth + 10;
                double fromHeight = fromT.ActualHeight + 10;
                // ---


                double toX = polyline[2].X2 + 3;
                double toY = polyline[2].Y2 - 30;
                double toWidth = toT.ActualWidth + 10;
                double toHeight = toT.ActualHeight + 10;
                // ---
                toR.Width = toWidth;
                toR.Height = toHeight;
                Canvas.SetLeft(toR, toX);
                Canvas.SetTop(toR, toY);
                Canvas.SetLeft(toT, toX + 5);
                Canvas.SetTop(toT, toY + 5);
                
                fromR.Width = fromWidth;
                fromR.Height = fromHeight;
                Canvas.SetLeft(fromR, fromX);
                Canvas.SetTop(fromR, fromY);
                Canvas.SetLeft(fromT, fromX + 5);
                Canvas.SetTop(fromT, fromY + 5);
            }
            else if (fromConnectionPoint == ConnectionPoint.NORTH)
            {
                double fromX = polyline[0].X1 + 3;
                double fromY = polyline[0].Y1 - 30;
                double fromWidth = fromT.ActualWidth + 10;
                double fromHeight = fromT.ActualHeight + 10;
                // ---


                double toX = polyline[2].X2 + 3;
                double toY = polyline[2].Y2 + 3;
                double toWidth = toT.ActualWidth + 10;
                double toHeight = toT.ActualHeight + 10;
                // ---
                toR.Width = toWidth;
                toR.Height = toHeight;
                Canvas.SetLeft(toR, toX);
                Canvas.SetTop(toR, toY);
                Canvas.SetLeft(toT, toX + 5);
                Canvas.SetTop(toT, toY + 5);

                fromR.Width = fromWidth;
                fromR.Height = fromHeight;
                Canvas.SetLeft(fromR, fromX);
                Canvas.SetTop(fromR, fromY);
                Canvas.SetLeft(fromT, fromX + 5);
                Canvas.SetTop(fromT, fromY + 5);
            }
        }

        private void InitTextBlocks()
        {
            fromR = new Rectangle();
            toR = new Rectangle();            

            fromR.Stroke = toR.Stroke = Brushes.Black;
            fromR.StrokeThickness = toR.StrokeThickness = 1;
            fromR.Fill = toR.Fill = new SolidColorBrush(Color.FromArgb(10, 255, 255, 255));
            fromR.StrokeDashArray.Add(5);
            toR.StrokeDashArray.Add(5);            

            fromT = new TextBlock();
            toT = new TextBlock();
            fromT.Text = " fromText ";
            toT.Text = " toText ";
            fromT.SizeChanged += new SizeChangedEventHandler(fromT_SizeChanged);
            toT.SizeChanged += new SizeChangedEventHandler(fromT_SizeChanged);

            guml.panel.Children.Add(fromR);
            guml.panel.Children.Add(toR);

            guml.panel.Children.Add(fromT);
            guml.panel.Children.Add(toT);

            fromR.MouseDown += from_MouseDown;
            fromT.MouseDown += from_MouseDown;

            toR.MouseDown += to_MouseDown;
            toT.MouseDown += to_MouseDown;


        }

        void fromT_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            setTextBlockPositions();
        }
        
        public enum AssociactionDirection { FROM, TO }
       
        public void setPointFrom(double px, double py)
        {            
            pFrom = new Point(px, py);
        }

        public void setPointTo(double px, double py)
        {
            pTo = new Point(px, py);
        }

        private void PolylineBringToFront()
        {
         /*   for (int i = 0; i < polyline.Length; i++)
            {
                guml.panel.Children.Remove(polyline[i]);
                guml.panel.Children.Add(polyline[i]);
            }*/
        }

        public void calculatePolyline()
        {
            int oWidth = (int)(pTo.X - pFrom.X);
            int oHeight = (int)(pTo.Y - pFrom.Y);
            double x1,y1,x2,y2,x3,y3,x4,y4;
            x1 = x2 = x3 = x4 = y1 = y2 = y3 = y4 = 0;
            if (fromConnectionPoint == ConnectionPoint.EAST)
            {
                x1 = pFrom.X;
                y1 = pFrom.Y;
                x2 = x1 + oWidth / 2.0f;
                y2 = y1;
                x3 = x2;
                y3 = pTo.Y;  
                x4 = pTo.X;
                y4 = y3;            
            }
            else if (fromConnectionPoint == ConnectionPoint.WEST)
            {
                oWidth = (int)(pFrom.X - pTo.X);
                x1 = pTo.X;
                y1 = pTo.Y;
                x2 = x1 + oWidth / 2.0f;
                y2 = y1;
                x3 = x2;
                y3 = pFrom.Y;
                x4 = pFrom.X;
                y4 = y3;
            }
            else if (fromConnectionPoint == ConnectionPoint.NORTH)
            {
                oHeight = (int)(pFrom.Y - pTo.Y);
                x1 = pTo.X;
                y1 = pTo.Y;
                x2 = x1;
                y2 = y1 + oHeight / 2.0f;
                x3 = pFrom.X;
                y3 = y2;
                x4 = x3;
                y4 = pFrom.Y;
            }
            else if (fromConnectionPoint == ConnectionPoint.SOUTH)
            {
                x1 = pFrom.X;
                y1 = pFrom.Y;
                x2 = x1;
                y2 = y1 + oHeight / 2.0f;
                x3 = pTo.X;
                y3 = y2;
                x4 = x3;
                y4 = pTo.Y;
            }

            if (((Diagram.Asocjacja)guml.obj_uml)[0].EndType != ModelUML.AsocjacjaUML.EndTypeEnum.brak)
            {
                if (fromConnectionPoint == ConnectionPoint.EAST) x1 += 10;
                if (fromConnectionPoint == ConnectionPoint.WEST) x1 -= 10;
                if (fromConnectionPoint == ConnectionPoint.NORTH) y1 -= 10;
                if (fromConnectionPoint == ConnectionPoint.SOUTH) y1 += 10;
            }

            if (((Diagram.Asocjacja)guml.obj_uml)[1].EndType != ModelUML.AsocjacjaUML.EndTypeEnum.brak)
            {
                if (toConnectionPoint == ConnectionPoint.EAST) x4 += 10;
                if (toConnectionPoint == ConnectionPoint.WEST) x4 -= 10;
                if (toConnectionPoint == ConnectionPoint.NORTH) y4 -= 10;
                if (toConnectionPoint == ConnectionPoint.SOUTH) y4 += 10;
            }

            PolylineBringToFront();

            polyline[0].X1 = x1;
            polyline[0].Y1 = y1;
            polyline[0].X2 = x2;
            polyline[0].Y2 = y2;

            polyline[1].X1 = x2;
            polyline[1].Y1 = y2;
            polyline[1].X2 = x3;
            polyline[1].Y2 = y3;

            polyline[2].X1 = x3;
            polyline[2].Y1 = y3;
            polyline[2].X2 = x4;
            polyline[2].Y2 = y4;

            setTextBlockPositions();

        }

        public void setFromConnectionPoint(ConnectionPoint connectionPoint)
        {
            fromConnectionPoint = connectionPoint;
        }

        public void setToConnectionPoint(ConnectionPoint connectionPoint)
        {
            toConnectionPoint = connectionPoint;
        }

        public ConnectionPoint getFromConnectionPoint()
        {
            return fromConnectionPoint;
        }

        public ConnectionPoint getToConnectionPoint()
        {
            return toConnectionPoint;
        }

        public LineType getLineType()
        {
            return lineType;
        }

        public void Move(int delta,AssociactionDirection dir)
        {            
            if (dir == AssociactionDirection.FROM)
            {
                if ((fromConnectionPoint == ConnectionPoint.WEST) || (fromConnectionPoint == ConnectionPoint.EAST))
                {
                    pFrom.Y += delta;
                }
                else if ((fromConnectionPoint == ConnectionPoint.NORTH) || (fromConnectionPoint == ConnectionPoint.SOUTH))
                {
                    pFrom.X += delta;
                }
            }
            else if (dir == AssociactionDirection.TO)
            {
                if ((toConnectionPoint == ConnectionPoint.WEST) || (toConnectionPoint == ConnectionPoint.EAST))
                {
                    pTo.Y += delta;
                }
                else if ((toConnectionPoint == ConnectionPoint.NORTH) || (toConnectionPoint == ConnectionPoint.SOUTH))
                {
                    pTo.X += delta;
                }
            }
            calculatePolyline();
        }

        public void setPolyline(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)
        {
            lx1 = x1;
            lx2 = x2;
            lx3 = x3;
            lx4 = x4;
            ly1 = y1;
            ly2 = y2;
            ly3 = y3;
            ly4 = y4;

            polyline[0].X1 = x1;
            polyline[0].Y1 = y1;
            polyline[0].X2 = x2;
            polyline[0].Y2 = y2;

            polyline[1].X1 = x2;
            polyline[1].Y1 = y2;
            polyline[1].X2 = x3;
            polyline[1].Y2 = y3;

            polyline[2].X1 = x3;
            polyline[2].Y1 = y3;
            polyline[2].X2 = x4;
            polyline[2].Y2 = y4;            
        }

        public void setLineType(LineType lineType) 
        {
            this.lineType = lineType;
            if (lineType == LineType.CORNERED)
            {

                line.Visibility = Visibility.Hidden;
                foreach (Line l in polyline) { l.Visibility = Visibility.Visible; }
            }
            else if (lineType == LineType.CURVE)
            {
                line.Visibility = Visibility.Visible;
                foreach (Line l in polyline) { l.Visibility = Visibility.Hidden; }
            }
        }

        public void setLineStart(double px,double py) 
        {
            line.X1 = px;
            line.Y1 = py;
        }

        public void setLineEnd(double px, double py)
        {
            line.X2 = px;
            line.Y2 = py;
        }

        public PointCollection getPointsFromShape(ModelUML.AsocjacjaUML.EndTypeEnum typeModel,double aX, double aY,ConnectionPoint pt)
        {                        
            PointCollection points = new PointCollection();
            if (typeModel == ModelUML.AsocjacjaUML.EndTypeEnum.brak)
            {
                return points;
            }

            else if ((typeModel == ModelUML.AsocjacjaUML.EndTypeEnum.generalizacja))
            {
                if (pt == ConnectionPoint.EAST)
                {
                    points.Add(new Point(aX, aY - 5));
                    points.Add(new Point(aX, aY + 5));
                    points.Add(new Point(aX - 10, aY));
                    points.Add(new Point(aX, aY - 5));
                }
                else if (pt == ConnectionPoint.WEST)
                {
                    points.Add(new Point(aX, aY - 5));
                    points.Add(new Point(aX, aY + 5));
                    points.Add(new Point(aX + 10, aY));
                    points.Add(new Point(aX, aY - 5));
                }
                else if (pt == ConnectionPoint.NORTH)
                {
                    points.Add(new Point(aX - 5, aY));
                    points.Add(new Point(aX + 5, aY));
                    points.Add(new Point(aX, aY + 10));
                    points.Add(new Point(aX - 5, aY));
                }
                else if (pt == ConnectionPoint.SOUTH)
                {
                    points.Add(new Point(aX - 5, aY));
                    points.Add(new Point(aX + 5, aY));
                    points.Add(new Point(aX, aY - 10));
                    points.Add(new Point(aX - 5, aY));
                }
            }
            else if ((typeModel == ModelUML.AsocjacjaUML.EndTypeEnum.kompozycja) || (typeModel == ModelUML.AsocjacjaUML.EndTypeEnum.agregacja))
            {
                if ((pt == ConnectionPoint.EAST))
                {
                    points.Add(new Point(aX - 10, aY));
                    points.Add(new Point(aX - 5, aY + 5));
                    points.Add(new Point(aX, aY));
                    points.Add(new Point(aX - 5, aY - 5));
                    points.Add(new Point(aX - 10, aY));
                }
                else if (pt == ConnectionPoint.WEST) 
                {
                    points.Add(new Point(aX, aY));
                    points.Add(new Point(aX+5,aY+5));
                    points.Add(new Point(aX + 10, aY));
                    points.Add(new Point(aX + 5, aY - 5));
                    points.Add(new Point(aX, aY));
                }
                else if (pt == ConnectionPoint.NORTH)
                {
                    points.Add(new Point(aX - 5, aY+5));
                    points.Add(new Point(aX , aY+10));
                    points.Add(new Point(aX+5, aY+5));
                    points.Add(new Point(aX,aY));
                    points.Add(new Point(aX -5, aY+5));
                }
                else if (pt == ConnectionPoint.SOUTH)
                {
                    points.Add(new Point(aX - 5, aY - 5));
                    points.Add(new Point(aX, aY));
                    points.Add(new Point(aX+5, aY-5));
                    points.Add(new Point(aX, aY - 10));
                    points.Add(new Point(aX - 5, aY - 5));
                }
            }
            return points;
        }

        // uaktualnia pozycje strzalek po poruszeniu klasą
        public void updateEndings(bool updateClassDependecies)
        {
           
            if (updateClassDependecies)
            {
                fromRef.updateDependencyProperties();
                toRef.updateDependencyProperties();
            }


            if (lineType == LineType.CURVE)
            {
                /*
                PointCollection points = null;
                // from ending
                points = getPointsFromShape(fromType, line.X1, line.Y1, AssociactionDirection.FROM);
                fromPolygon.SetValue(Polygon.PointsProperty, points);
                if ((fromType == AssociationShape.QUAD_FULL) || (fromType == AssociationShape.ARROW_FULL))
                    fromPolygon.Fill = Brushes.Black;
                else
                    fromPolygon.Fill = Brushes.Transparent;


                // to ending
                points = null;
                points = getPointsFromShape(toType, line.X2, line.Y2, AssociactionDirection.TO);
                toPolygon.SetValue(Polygon.PointsProperty, points);
                if ((toType == AssociationShape.QUAD_FULL) || (toType == AssociationShape.ARROW_FULL))
                    toPolygon.Fill = Brushes.Black;
                else
                    toPolygon.Fill = Brushes.Transparent;

                // uaktualnij polozenia obiektow odpowiedzialnych za podswietlenie hinta asocacji
                Canvas.SetLeft(fromMenu, line.X1 - 10);
                Canvas.SetTop(fromMenu, line.Y1 - 10);
                Canvas.SetLeft(toMenu, line.X2 - 10);
                Canvas.SetTop(toMenu, line.Y2 - 10);*/
            }
            else if (lineType == LineType.CORNERED)
            {
                Diagram.Asocjacja dAso = guml.obj_uml as Diagram.Asocjacja;
                ModelUML.AsocjacjaUML.EndTypeEnum fromType = dAso[0].EndType;
                ModelUML.AsocjacjaUML.EndTypeEnum toType = dAso[1].EndType;
                PointCollection points = null;
                points = getPointsFromShape((guml.obj_uml as Diagram.Asocjacja)[0].EndType, polyline[0].X1, polyline[0].Y1, fromConnectionPoint);
                fromPolygon.SetValue(Polygon.PointsProperty, points);
                if ((fromType == ModelUML.AsocjacjaUML.EndTypeEnum.kompozycja))
                    fromPolygon.Fill = Brushes.Black;
                else
                    fromPolygon.Fill = Brushes.Transparent;


                points = getPointsFromShape((guml.obj_uml as Diagram.Asocjacja)[1].EndType, polyline[2].X2, polyline[2].Y2, toConnectionPoint);
                toPolygon.SetValue(Polygon.PointsProperty, points);
                if ((toType == ModelUML.AsocjacjaUML.EndTypeEnum.kompozycja))
                    toPolygon.Fill = Brushes.Black;
                else
                    toPolygon.Fill = Brushes.Transparent;


                int fromDelta = fromType == 0 ? 0 : 10;
                int toDelta = toType == 0 ? 0 : 10;
                if (fromConnectionPoint == ConnectionPoint.EAST)
                {
                    Canvas.SetLeft(fromMenu, polyline[0].X1 - fromDelta);
                    Canvas.SetTop(fromMenu, polyline[0].Y1 - 10);                    
                }
                else if (fromConnectionPoint == ConnectionPoint.WEST)
                {
                    Canvas.SetLeft(fromMenu, polyline[0].X1 - 20 + fromDelta);
                    Canvas.SetTop(fromMenu, polyline[0].Y1 - 10);
                }
                else if (fromConnectionPoint == ConnectionPoint.NORTH)
                {
                    Canvas.SetLeft(fromMenu, polyline[0].X1 - 10);
                    Canvas.SetTop(fromMenu, polyline[0].Y1 - 20 + fromDelta);
                }
                else if (fromConnectionPoint == ConnectionPoint.SOUTH)
                {
                    Canvas.SetLeft(fromMenu, polyline[0].X1 - 10);
                    Canvas.SetTop(fromMenu, polyline[0].Y1 - fromDelta);
                }

                if (toConnectionPoint == ConnectionPoint.EAST)
                {
                    Canvas.SetLeft(toMenu, polyline[2].X2 - toDelta);
                    Canvas.SetTop(toMenu, polyline[2].Y2 - 10);
                }
                else if (toConnectionPoint == ConnectionPoint.WEST)
                {
                    Canvas.SetLeft(toMenu, polyline[2].X2 - 20 + toDelta);
                    Canvas.SetTop(toMenu, polyline[2].Y2 - 10);
                }
                else if (toConnectionPoint == ConnectionPoint.NORTH)
                {
                    Canvas.SetLeft(toMenu, polyline[2].X2 - 10);
                    Canvas.SetTop(toMenu, polyline[2].Y2 - 20 + toDelta);
                }
                else if (toConnectionPoint == ConnectionPoint.SOUTH)
                {
                    Canvas.SetLeft(toMenu, polyline[2].X2 - 10);
                    Canvas.SetTop(toMenu, polyline[2].Y2 - toDelta);
                }                
            }
        }

        public void menuMouseEnter(object sender, RoutedEventArgs e)
        {            
            double px,py;
            px = py = 0;

            OurCanvas p = guml.panel.Parent as OurCanvas;
            p.Children.Remove(guml.panel);
            p.Children.Add(guml.panel);

            if (sender.Equals(fromMenu))
            {                
                associationHintFrom.setDirection(AssociactionDirection.FROM);
                if (lineType == LineType.CURVE)
                {
                    px = line.X1;
                    py = line.Y1 - 20;
                }
                else if (lineType == LineType.CORNERED)
                {
                    if ((fromConnectionPoint == ConnectionPoint.EAST) || (fromConnectionPoint == ConnectionPoint.WEST))
                    {
                        px = polyline[0].X1;
                        py = polyline[0].Y1 - 20;
                    }
                    else
                    {
                        px = polyline[0].X1 - 20;
                        py = polyline[0].Y1 ;
                    }
                }



                associationHintFrom.setConnectionPoint(fromConnectionPoint);
                associationHintFrom.setPosition(px, py);
                associationHintFrom.setShowing(true);
                DoubleAnimation dAnim = new DoubleAnimation(0.01, 0.6, new System.TimeSpan(0, 0, 0, 0, 300), FillBehavior.Stop);
                dAnim.AutoReverse = true;
                (sender as Canvas).BeginAnimation(Canvas.OpacityProperty, dAnim);
            }
            else
            {
                associationHintTo.setDirection(AssociactionDirection.TO);

                if (lineType == LineType.CURVE)
                {
                    px = line.X2 - 40;
                    py = line.Y2 - 20;
                }
                else if (lineType == LineType.CORNERED)
                {
                    if ((toConnectionPoint == ConnectionPoint.EAST) || (toConnectionPoint == ConnectionPoint.WEST))
                    {
                        px = polyline[2].X2;
                        py = polyline[2].Y2 - 20;
                    }
                    else
                    {
                        px = polyline[2].X2 - 20;
                        py = polyline[2].Y2;
                    }
                }
                
                associationHintTo.setConnectionPoint(toConnectionPoint);
                associationHintTo.setPosition(px, py);
                associationHintTo.setShowing(true);
                DoubleAnimation dAnim = new DoubleAnimation(0.01, 0.6, new System.TimeSpan(0, 0, 0, 0, 300), FillBehavior.Stop);
                dAnim.AutoReverse = true;
                (sender as Canvas).BeginAnimation(Canvas.OpacityProperty, dAnim);
            }            
        }

        public void menuMouseLeave(object sender, RoutedEventArgs e)
        {            
        }

        public AssociationObj(AssociableObj fromRef, AssociableObj toRef, GUML aguml, OurCanvas a_canvas)
            : base(aguml)
        {
            ((Diagram.Asocjacja)guml.obj_uml)[0].Tekst = "...";
            ((Diagram.Asocjacja)guml.obj_uml)[1].Tekst = "...";
            guml.canvas = a_canvas;
            canChooseType = true;

            if ((fromRef is NotatkaObj) || (toRef is NotatkaObj))
            {
                canChooseType = false;
            }

            this.lineType = LineType.CURVE;
            this.fromRef = fromRef;
            this.toRef = toRef;
            this.guml.panel = new Canvas();            
            this.guml.panel.Background = Brushes.Transparent;            
            line.StrokeThickness = 1;
            line.Stroke = Brushes.Black;
            fromRef.addAsociation(this);
            toRef.addAsociation(this);
            guml.panel.Children.Add(line);

            for (int i = 0; i < polyline.Length; i++)
            {
                polyline[i] = new Line();
                polyline[i].SnapsToDevicePixels = true;
                polyline[i].Visibility = Visibility.Hidden;
                polyline[i].Stroke = Brushes.Black;
                polyline[i].StrokeThickness = 1;

                if (!canChooseType)
                {
                    polyline[i].StrokeDashArray.Add(5);
                }

                guml.panel.Children.Add(polyline[i]);
            }

            a_canvas.Children.Add(guml.panel);
                       
            
            fromPolygon.Stroke = toPolygon.Stroke = Brushes.Black;
            fromPolygon.StrokeThickness = toPolygon.StrokeThickness = 1;            
            guml.panel.Children.Add(fromPolygon);
            guml.panel.Children.Add(toPolygon);
            
            fromMenu.Background = Brushes.White;
            toMenu.Background = Brushes.White;

            if (canChooseType)
            {
                fromMenu.Opacity = toMenu.Opacity = 0.01f;
            }
            else
            {
                fromMenu.Opacity = toMenu.Opacity = 0.0f;
                fromMenu.Visibility = toMenu.Visibility = Visibility.Hidden;                
            }

            fromRef.updateDependencyProperties();
            toRef.updateDependencyProperties();            
            guml.panel.Children.Add(fromMenu);
            guml.panel.Children.Add(toMenu);            
            fromMenu.Width = toMenu.Width = fromMenu.Height = toMenu.Height = 20;
            fromMenu.MouseEnter += menuMouseEnter;
            toMenu.MouseEnter += menuMouseEnter;


            InitTextBlocks();
            

            // menu asocjacji
            associationHintFrom = new AssociationHint(this, 0, 0);
            associationHintFrom.Visibility = Visibility.Hidden;
            associationHintTo = new AssociationHint(this, 0, 0);
            associationHintTo.Visibility = Visibility.Hidden;
            guml.panel.Children.Add(associationHintFrom);
            guml.panel.Children.Add(associationHintTo);
            setLineType(LineType.CORNERED);
            updateEndings(true);
            ((Diagram.Asocjacja)guml.obj_uml)[0].EndType = ModelUML.AsocjacjaUML.EndTypeEnum.brak;
            ((Diagram.Asocjacja)guml.obj_uml)[1].EndType = ModelUML.AsocjacjaUML.EndTypeEnum.brak;
        }
    }
}
